package murgtug.mediamanager.client;

import java.util.List;

import murgtug.mediamanager.shared.model.Album;
import murgtug.mediamanager.shared.model.Artist;
import murgtug.mediamanager.shared.model.Song;
import murgtug.mediamanager.shared.service.AudioService;
import murgtug.mediamanager.shared.service.AudioServiceAsync;

import com.google.gwt.canvas.client.Canvas;
import com.google.gwt.canvas.dom.client.Context2d;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.media.client.Audio;
import com.google.gwt.storage.client.Storage;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.RadioButton;
import com.google.gwt.user.client.ui.Widget;

public class MainView extends Composite {

	private static MainViewImplUiBinder uiBinder = GWT.create(MainViewImplUiBinder.class);

	interface MainViewImplUiBinder extends UiBinder<Widget, MainView> {
	}

	private AudioServiceAsync audioService = GWT.create(AudioService.class);
	
	@UiField ListBox artistsListBox;
	@UiField ListBox albumsListBox;
	@UiField ListBox songsListBox;
	
	@UiField Label nowPlayingLabel;
	
	@UiField RadioButton radioButton1;
	@UiField RadioButton radioButton2;
	@UiField RadioButton radioButton3;
	@UiField RadioButton radioButton4;
	@UiField RadioButton radioButton5;
	
	@UiField(provided = true) Audio audioPlayer = Audio.createIfSupported();
	
	@UiField(provided = true) Canvas canvas = Canvas.createIfSupported();
	
	private Storage localStorage = Storage.getLocalStorageIfSupported();

	public MainView() {
		GWT.log(audioPlayer.getPreload());
		initWidget(uiBinder.createAndBindUi(this));
		drawCheesyRating(1);
	}

	public void init() {
		nowPlayingLabel.setText("");
		loadArtists();
	}

	private void loadArtists() {
		
		artistsListBox.clear();
		albumsListBox.clear();
		songsListBox.clear();
		
		audioService.getArtists(new AsyncCallback<List<Artist>>() {
			
			@Override
			public void onSuccess(List<Artist> result) {
				for (Artist artist: result) {
					artistsListBox.addItem(artist.getName(), String.valueOf(artist.getId()));
				}
			}
			
			@Override
			public void onFailure(Throwable caught) {
				artistsListBox.clear();
				albumsListBox.clear();
				songsListBox.clear();
				Window.alert("Artists load error: " + caught.getMessage());
			}
		});
	}
	
	private void loadAlbums(final int artistId) {
		
		albumsListBox.clear();
		songsListBox.clear();
		
		audioService.getArtistAlbums(artistId, new AsyncCallback<List<Album>>() {

			@Override
			public void onFailure(Throwable caught) {
				songsListBox.clear();
				Window.alert("Albums load error for id " + artistId + ": " + caught.getMessage());
			}

			@Override
			public void onSuccess(List<Album> result) {
				for (Album album: result) {
					albumsListBox.addItem(album.getName(), String.valueOf(album.getId()));
				}
			}
		});
	}
	
	private void loadSongs(final int artistId, final int albumId) {
		
		songsListBox.clear();
		
		audioService.getAlbumSongs(artistId, albumId, new AsyncCallback<List<Song>>() {

			@Override
			public void onFailure(Throwable caught) {
				Window.alert("Songs load error for id " + albumId + ": " + caught.getMessage());
			}

			@Override
			public void onSuccess(List<Song> result) {
				for (Song song: result) {
					songsListBox.addItem(
							song.getTrackNr() + " - " + song.getTitle(), 
							String.valueOf(song.getId()));
				}
			}
		});
		
	}
	
	@UiHandler("artistsListBox")
	void onArtistChange(ChangeEvent event) {
		int artistId = Integer.parseInt(artistsListBox.getValue(artistsListBox.getSelectedIndex()));
		if (artistId == -1) {
			albumsListBox.clear();
		} else {
			loadAlbums(artistId);
		}
	}
	
	@UiHandler("albumsListBox")
	void onAlbumChange(ChangeEvent event) {
		int albumId = Integer.parseInt(albumsListBox.getValue(albumsListBox.getSelectedIndex()));
		if (albumId == -1) {
			songsListBox.clear();
		} else {
			int artistId = Integer.parseInt(artistsListBox.getValue(artistsListBox.getSelectedIndex()));
			loadSongs(artistId, albumId);
		}
	}
	
	@UiHandler("songsListBox")
	void onSongChange(ChangeEvent event) {
		int songId = getListValueAsInt(songsListBox);
		if (songId == -1) {
			nowPlayingLabel.setText("");
		} else {
			int artistId = getListValueAsInt(artistsListBox);
			int albumId = getListValueAsInt(albumsListBox);
			String url = GWT.getModuleBaseURL() 
				+ "file?artist_id=" + artistId 
				+ "&album_id=" + albumId
				+ "&song_id=" + songId;
			GWT.log(url);
			audioPlayer.setSrc(url);
			
			nowPlayingLabel.setText(
					getListSelectedItemText(artistsListBox)
					+ " :: "
					+ getListSelectedItemText(albumsListBox) 
					+ " :: "
					+ getListSelectedItemText(songsListBox));

			String ratingStr = localStorage.getItem("song_id_" + getListValueAsInt(songsListBox));
			int rating;
			if (ratingStr == null) {
				radioButton1.setValue(true);
				rating = 1;
			} else {
				rating = Integer.parseInt(ratingStr);
				switch (rating) {
				case 1:
					radioButton1.setValue(true);
					break;
				case 2:
					radioButton2.setValue(true);
					break;
				case 3:
					radioButton3.setValue(true);
					break;
				case 4:
					radioButton4.setValue(true);
					break;
				case 5:
					radioButton5.setValue(true);
					break;
				default:
					break;
				} 
			}
			
			drawCheesyRating(rating);
		}
	}

	private int getListValueAsInt(ListBox listBox) {
		return Integer.parseInt(listBox.getValue(listBox.getSelectedIndex()));
	}
	
	private String getListSelectedItemText(ListBox listBox) {
		return listBox.getItemText(listBox.getSelectedIndex());
	}
	
	@UiHandler({"radioButton1", "radioButton2", "radioButton3", "radioButton4", "radioButton5"})
	void onRadioButtonStateChange(ValueChangeEvent<Boolean> event) {
		RadioButton rb = (RadioButton) event.getSource();
		int rating = Integer.parseInt(rb.getText());

		if (songsListBox.getSelectedIndex() != -1) {
			localStorage.setItem("song_id_" + getListValueAsInt(songsListBox), "" + rating);
		}
		
		drawCheesyRating(rating);
	}
	
	private void drawCheesyRating(int rating) {

		Context2d context = canvas.getContext2d();
		
		int w = context.getCanvas().getWidth();
		int h = context.getCanvas().getHeight();

		context.setFillStyle("black");
		
		context.fillRect(0, 0, w, h);
		
		context.setFillStyle("gray");
		
		context.beginPath();
		context.moveTo(w/2, h/2);
		context.arc(canvas.getCanvasElement().getWidth() / 2,
				    canvas.getCanvasElement().getHeight() / 2,
				    Math.min(w/2, h/2),
				    0, 
				    2 * Math.PI);
		context.closePath();
		//context.stroke();
		context.fill();
		
		context.setFillStyle("green");
		
		context.beginPath();
		context.moveTo(w/2, h/2);
		context.lineTo(w, h/2);
		context.arc(canvas.getCanvasElement().getWidth() / 2,
				    canvas.getCanvasElement().getHeight() / 2,
				    Math.min(w/2, h/2),
				    0, 
				    2 * Math.PI * rating / 5);
		context.closePath();
		//context.stroke();
		context.fill();
	}
}
